package src.model.gameObject.ability;

import src.model.gameObject.GameObject;
import src.model.gameWorld.LookupTable;

/**
 * @author Tristan
 * <b>Overview:</b><br>
 * This class represents abilities. These are the behaviors that define a GameObject,
 * and ALL of the behaviors of said GameObjects. Our abilities are basically our game event managers.<br>
 * <br>
 * <b>Responsibilities:</b><br>
 * To provide a common interface to talk to abilities.<br>
 * </br>
 * <b>Collaborators:</b><br>
 * <ul>
 * <li>GameObject - The GameObject that owns this. Abilities need to know their owner so that they may perform actions
 * that affect other abilities belonging to that owner (modify health, etc.)</li>
 * <li>AbilityType - The Type of this ability, to identify its ability.</li>
 * <li>LookupTable - To refer to in order to fetch ability attribute values.</li>
 * </ul>
 * <br>
 * <b>Implementor:</b><br>
 * Tristan Lohman<br>
 * <br>
 * <b>Tester:</b><br>
 * Brent Moffitt
 */
public abstract class Ability {

	private GameObject go;		// The GO that this ability belongs to.
	private AbilityType aType;	// The type of ability that this is.
	private LookupTable lookup;
	
	/**
	 * Constructs an ability of AbilityType aType, belonging to GameObject go.
	 * @param go The GameObject owning this.
	 * @param aType The AbilityType representing this Ability.
	 * @param lookup The lookup table that this will refer to.
	 */
	public Ability(GameObject go, AbilityType aType, LookupTable lookup) {
		this.go = go;
		this.aType = aType;
		this.lookup = lookup;
	}
	
	/**
	 * Fetches the GameObject associated with this Ability.
	 * @return the owning GameObject.
	 */
	public GameObject gameObject(){ return go; }
	
	/**
	 * Determines the type of Ability that this represents.
	 * @return The type of ability that this is.
	 */
	public AbilityType abilityType(){ return aType; }
	
	protected LookupTable lookupTable(){return lookup;}
	
	/**
	 * Returns this ability's attribute value of either minimum, maximum, or strength.
	 * This assumes that the ability that this is called on actually has the requested value.
	 * @param aa The attribute value requested.
	 * @return The value of said attribute.
	 */
	public float getAttribute(AbilityAttributes aa){
		return lookup.statQuery(go.getType(), go.getSubtype(), aType, aa);
	}
	
	/**
	 * This is called to tell the ability to destroy itself. This is called when the GameObject
	 * is destroyed. This is required to have the ability to remove its reference to it's owning
	 * GameObject.It then tells any subclassed abilities to 
	 * 
	 */
	public void destroyMe(){
		this.go = null;
		this.aType = null;
		this.destroySub();
	}
	
	/**
	 * This allows this to tell it's sub-ability to destroy itself. This tells them to do things like
	 * unregisterng from the game world and all brokers.
	 *
	 */
	public abstract void destroySub();
	
	/**
	 * This method may be overridden to allow Abilities to
	 * be informed of new turns.
	 */
	public void newTurn(){};
}
